﻿using BaseUtils.Logger;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DriveManage.SocketClient
{
    public class SocketClientManager : ISocketHandler
    {
        private Socket _socket;
        private EndPoint endPoint;
        private bool _isConnected;
        private bool _isClickDisconnect;
        private bool _isClickStart;
        private bool _isConnecting;
        private bool _isReConnectClose;
        private int _isReConnectTryMaxNum;
        private int _currentReTryNum;
        public string Name { get; set; }

        /// <summary>
        /// 接收的数据缓存
        /// </summary>
        public StringBuilder _ReceiveDataCache { get; set; } = new StringBuilder();

        public int ReceiveTimeout { get; set; } = 2000;
        public int SendTimeout { get; set; } = 2000;
        public string Terminal => _Terminal;
        public string _Terminal = "";
        /// <summary>
        /// 重连机制
        /// 最大重连次数 MaxReconnectAttempts
        /// 重连间隔时间，随着次数成倍增长 BaseReconnectInterval
        /// </summary>
        private int BaseReconnectInterval = 1000;
        private int MaxReconnectAttempts = 12;
        private int CurrentReconnectAttempt = 0;

        private string msg = "";
        private byte[] buffer = new byte[2048];

        public bool IsConnected => _isConnected;
        public StringBuilder ReceiveDataCache => _ReceiveDataCache;

        public List<TcpClient> ConnectedClients => throw new NotImplementedException();

        public event OnConnectedHandler OnConnected;
        public event OnConnectedHandler OnFaildConnect;
        public event OnReceiveMsgHandler OnReceiveMsg;
        public event ConnectErrorHandler OnConnectError;
        public event ClientConnectedEventHandler OnClientConnected;
        public event ClientDisconnectedEventHandler OnClientDisconnected;
        public event MessageReceivedEventHandler OnMessageReceived;

        public SocketClientManager(string _Ip, int _Port, int _ReceiveTimeout, int _SendTimeout, string _Name)
        {
            _Terminal = "client";
            Name = _Name;
            ReceiveTimeout = _ReceiveTimeout;
            SendTimeout = _SendTimeout;
            try
            {
                IPAddress address = IPAddress.Parse(_Ip);
                endPoint = new IPEndPoint(address, _Port);
            }
            catch (Exception ex)
            {
                LoggerService.Error($"Socket 连接初始化失败,ip={_Ip},port={_Port}", ex);
            }
        }

        /// <summary>
        /// 关闭连接
        /// </summary>
        public void Disconnect()
        {
            if (_socket != null)
            {
                if (_socket.Connected)
                {
                    try
                    {
                        _socket.Shutdown(SocketShutdown.Both);
                    }
                    catch (Exception)
                    {
                    }
                    _socket.Disconnect(true);
                }

                _socket.Close();
            }
            _socket = null;
            _isConnected = false;
        }

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="Message"></param>
        public void SendMessage(string Message)
        {
            try
            {
                if (_socket == null || !_socket.Connected)
                {
                    Disconnect();
                    OnConnectError?.Invoke(this, "Socket连接为空，可能已断开");
                    return;
                }
                byte[] SengBuffer = Encoding.UTF8.GetBytes(Message);
                _socket.Send(SengBuffer);
            }
            catch (Exception ex)
            {
                Disconnect();
                string Error = $"消息发送失败:Message = {Message},其他信息 ={endPoint.ToString()}，{ex.ToString()}";
                OnConnectError?.Invoke(this, Error);
                LoggerService.Error(Error, ex);
            }
        }

        /// <summary>
        /// 开启连接
        /// </summary>
        /// <returns></returns>
        public bool Start()
        {
            bool _isConnecting2 = true;
            try
            {
                _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                if (_socket == null)
                {
                    LoggerService.Error($"Socket连接失败，endPoint={endPoint.ToString()}");
                    _isConnecting2 = false;
                    return _isConnecting;
                }
                _socket.BeginConnect(endPoint, SocketStartConnectedCallback, _socket);
                _socket.ReceiveTimeout = ReceiveTimeout;
                _socket.SendTimeout = SendTimeout;
            }
            catch (Exception ex)
            {
                _isConnecting2 = false;
                LoggerService.Error($"Socket连接失败，,endPoint={endPoint.ToString()}", ex);
                StartReconnect();
            }

            return _isConnecting2;
        }

        public void StartReconnect()
        {
            if (!_isConnecting && !_isConnected)
            {
                if (CurrentReconnectAttempt < MaxReconnectAttempts)
                {
                    Task.Run(() =>
                    {
                        int Interval = CalculateReconnectInterval();
                        Thread.Sleep(Interval);
                        CurrentReconnectAttempt++;
                        bool conn = _socket?.Connected ?? false;
                        if (!conn)
                        {
                            Start();
                        }
                    });
                }
                else
                {
                    LoggerService.Error($"Socket重连次数已达上限：{MaxReconnectAttempts}，停止重新连接");
                }
            }
        }

        private int CalculateReconnectInterval()
        {
            int interval = BaseReconnectInterval * (1 << CurrentReconnectAttempt);
            //return Math.Min(interval, MaxReconnectAttempts);
            return interval;
        }

        /// <summary>
        /// 连接成功或失败回调
        /// </summary>
        /// <param name="ar"></param>
        private void SocketStartConnectedCallback(IAsyncResult ar)
        {
            Socket socket = ar.AsyncState as Socket;
            _isConnecting = false;
            if (socket.Connected)
            {
                try
                {
                    socket.EndConnect(ar);
                    _isConnected = true;
                    BaseReconnectInterval = 1000;
                    CurrentReconnectAttempt = 0;
                    OnConnected?.Invoke(this);
                    _socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallback, socket);
                    // 连接成功，可在这里启动心跳相关逻辑（假设已有相关方法）
                }
                catch (SocketException ex)
                {
                    Disconnect();
                    OnConnectError?.Invoke(this, ex.ToString());
                }
            }
            else
            {
                Disconnect();
                OnFaildConnect?.Invoke(this);
            }
        }

        /// <summary>
        /// 接收消息回调
        /// </summary>
        /// <param name="ar"></param>
        private void ReceiveCallback(IAsyncResult ar)
        {
            try
            {
                if (_socket == null || _isClickDisconnect || !_isConnected)
                {
                    return;
                }
                Socket ts = (Socket)ar.AsyncState;
                if (ts == null) return;
                try
                {
                    ts.EndReceive(ar);
                    ar.AsyncWaitHandle.Close();
                }
                catch (Exception)
                {
                    Disconnect();
                    return;
                }
                if (buffer != null)
                {
                    msg = Encoding.UTF8.GetString(buffer).Replace("\0", "");
                }
                AddDataCache(msg);
                LoggerService.Info($"收到消息：{msg}");
                OnReceiveMsg?.Invoke(this, msg);
                buffer = new byte[2048];
                _socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallback, ts);
            }
            catch (SocketException ex)
            {
                Disconnect();
                OnConnectError?.Invoke(this, ex.ToString());
            }
        }

        public void AddDataCache(string msg)
        {
            _ReceiveDataCache.Append(msg);
            //_ReceiveDataCache.Add(msg);
            //if (_ReceiveDataCache?.Count > 100)
            //{
            //    _ReceiveDataCache.RemoveRange(_ReceiveDataCache.Count - 50, 50);
            //}
        }

        public bool Stop()
        {
            throw new NotImplementedException();
        }

        public bool HasConnectedClients()
        {
            throw new NotImplementedException();
        }

        public void SendMessage(TcpClient Client, string Message)
        {
            throw new NotImplementedException();
        }
    }
}
